home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "global.h"
- #include "timer.h"
- #include "proc.h"
- #include "pc.h"
-
- static struct timer *Timers; /* Head of running timer chain */
- int32 Clock;
-
- void
- timerproc(i,v1,v2)
- int i;
- void *v1,*v2;
- {
- register struct timer *t;
- register struct timer *expired = NULLTIMER;
- char i_state;
-
- for(;;){
- i_state = dirps(); /* Tick is modified by an interrupt */
- while(Tick == 0)
- pwait(&Tick);
- Tick--;
- restore(i_state);
-
- Clock++;
- systick(); /* Machine-dependent per-tick stuff */
-
- /* Decrement the first timer. If it expires,
- * take it off the running list and put it
- * on a singly linked list of expired timers
- */
- if(Timers != NULLTIMER)
- Timers->count--;
- else
- continue; /* Nothing else on this tick */
-
- while(Timers != NULLTIMER && Timers->count <= 0){
- if(Timers->next == Timers){
- printf("PANIC: Timer loop at %lx\n",
- (long)Timers);
- iostop();
- exit(1);
- }
- /* Save Timers since stop_timer will change it */
- t = Timers;
- stop_timer(t);
- t->state = TIMER_EXPIRE;
- /* Add to expired timer list */
- t->next = expired;
- expired = t;
- }
- /* Now go through the list of expired timers, removing each
- * one and kicking the notify function, if there is one
- */
- while((t = expired) != NULLTIMER){
- expired = t->next;
- if(t->func){
- (*t->func)(t->arg);
- }
- }
- }
- }
- /* Start a timer */
- void
- start_timer(t)
- struct timer *t;
- {
- register struct timer *tnext,*tprev;
- int32 tot;
-
- if(t == NULLTIMER)
- return;
- if(t->state == TIMER_RUN)
- stop_timer(t);
- if(t->start == 0)
- return; /* A start value of 0 disables the timer */
-
- t->state = TIMER_RUN;
- /* Find right place on list for this guy */
- tot = 0;
- tprev = NULLTIMER;
- for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
- if(tnext->count + tot > t->start)
- break;
- tprev = tnext;
- tot += tnext->count;
- }
- /* At this point, tprev points to the entry that should go right
- * before us, and tnext points to the entry just after us. Either or
- * both may be null.
- */
- t->count = t->start - tot; /* Adjust for entries before us */
- if((t->prev = tprev) == NULLTIMER)
- Timers = t; /* Put at beginning */
- else
- tprev->next = t;
-
- if((t->next = tnext) != NULLTIMER){
- tnext->prev = t;
- /* Adjust the following entry's count */
- tnext->count -= t->count;
- }
- }
- /* Stop a timer */
- void
- stop_timer(t)
- register struct timer *t;
- {
- register struct timer *tp;
-
- if(t == NULLTIMER)
- return;
- if(t->state == TIMER_RUN){
- /* Delete from active timer list */
- if(t->next != NULLTIMER)
- t->next->prev = t->prev;
- if(t->prev != NULLTIMER)
- t->prev->next = t->next;
- else
- Timers = t->next;
- /* Adjust count for the next timer */
- if((tp = t->next) != NULLTIMER)
- tp->count += t->count;
- }
- t->state = TIMER_STOP;
- }
- /* Return count of ticks remaining on this timer */
- int32
- read_timer(t)
- struct timer *t;
- {
- register struct timer *tp;
- int32 tot;
-
- if(t->state != TIMER_RUN)
- return 0;
-
- tot = 0;
- for(tp = Timers;tp != NULLTIMER; tp = tp->next){
- tot += tp->count;
- if(tp == t)
- break;
- }
- return tot;
- }
- /* Delay process for specified number of ticks */
- void
- pause(ticks)
- int32 ticks;
- {
- if(Curproc == NULLPROC || ticks == 0)
- return;
- alarm(ticks);
- /* The actual event doesn't matter, since we'll be alerted */
- while(Curproc->alarm.state == TIMER_RUN && pwait(Curproc) == 1)
- ;
-
- alarm(0L); /* Make sure it's stopped, in case we were killed */
- }
- static void
- t_alarm(x)
- void *x;
- {
- alert((struct proc *)x,1);
- }
- /* Send signal to current process after specified number of ticks */
- void
- alarm(ticks)
- int32 ticks;
- {
- if(Curproc != NULLPROC){
- Curproc->alarm.start = ticks;
- Curproc->alarm.func = t_alarm;
- Curproc->alarm.arg = (char *)Curproc;
- start_timer(&Curproc->alarm);
- }
- }
-
-